﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Heritage.Codebox;
using System.Security.Cryptography;
using System.Text;
using Heritage.Logging;

namespace Heritage.Controllers
{
    public class AuthController : BaseController
    {
        //
        // GET: /Auth/

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult SignIn(FormCollection coll)
        {
            string username = coll["username"];
            string password = coll["password"];
            string redir = Utils.SignIn(username, password, Response);
            if (redir != null)
            {
                LogService.Info(Utils.GetPrincipalName(), Constants.COMPONENT_SIGNIN, string.Format("User {0} signed in", username));
                return new RedirectResult(redir);
            }
            LogService.Warn(Utils.GetPrincipalName(), Constants.COMPONENT_SIGNIN, string.Format("Unsuccessful login attempt (user {0}, password {1})", username, password));
            return new RedirectResult("/Auth/WrongCreds");
        }
        public ActionResult Welcome()
        {
            if (Utils.IsAuthenticated())
            {
                return new RedirectResult("/Home/Personal");
            }
            return View();
        }
        public ActionResult Rules()
        {
            return View();
        }
        public ActionResult Register()
        {
            return View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Register(FormCollection coll)
        {
            if (coll["step"] == "0")
            {
                if (Utils.CheckCode(coll["code"]))
                {
                    ViewData["RegCode"] = coll["code"];
                    return View();
                }
                else
                {
                    return new RedirectResult("/Auth/WrongCode");
                }
            }
            else
            {
                if (string.IsNullOrEmpty(coll["username"]))
                {
                    ModelState.AddModelError("validate", "Имя пользователя не должно быть пустым");
                }
                else if (coll["username"].Length < 4 || coll["username"].Length > 30)
                {
                    ModelState.AddModelError("validate", "Имя пользователя должно содержать от 4 до 30 знаков");
                }
                if (string.IsNullOrEmpty(coll["password"]))
                {
                    ModelState.AddModelError("validate", "Пароль не должен быть пустым");
                }
                else if (coll["password"].Length < 6 || coll["password"].Length > 30)
                {
                    ModelState.AddModelError("validate", "Пароль должен содержать от 4 до 30 знаков");
                }
                if (coll["password"] != coll["password2"])
                {
                    ModelState.AddModelError("validate", "Пароли не совпадают");
                }
                if (coll["email"].IndexOf("@") < 0 || coll["email"].IndexOf(".") < 0 || coll["email"].LastIndexOf("@") > coll["email"].LastIndexOf("."))
                {
                    ModelState.AddModelError("validate", "Неверный формат адреса электронной почты");
                }
                if (Utils.CheckUserRegistered(coll["username"]))
                {
                    ModelState.AddModelError("validate", "Пользователь с этим именем уже зарегистрирован");
                }
                if (Utils.CheckEmailRegistered(coll["email"]))
                {
                    ModelState.AddModelError("validate", "Пользователь с этим почтовым адресом уже зарегистрирован");
                }
                if (!Utils.CheckCode(coll["code"]))
                {
                    ModelState.AddModelError("validate", "Неверный код подтверждения - пройдите регистрацию с начала!");
                }
                if (!ModelState.IsValid)
                {
                    ViewData["RegCode"] = coll["code"];
                    ViewData["Username"] = coll["username"];
                    ViewData["Email"] = coll["email"];
                    ViewData["Gender"] = coll["gender"];
                    return View();
                }
                else
                {
                    Guid userID = Guid.NewGuid();
                    string hash = Utils.HashString(coll["password"]);
                    Users user = Users.CreateUsers(userID, coll["username"], hash, coll["email"], Constants.USER_ROLE_JUNIOR, false, 0, false);
                    user.Referrer = Utils.GetReferrer(coll["code"]);
                    user.ValidationKey = Guid.NewGuid().ToString("N");
                    user.RegisterDate = DateTime.Now;
                    user.LastVisitDate = DateTime.Now;
                    HeritageEntities ents = new HeritageEntities();
                    ents.AddToUsers(user);
                    PersonalData data = PersonalData.CreatePersonalData(user.ID, 0, 0, true);
                    data.Gender = coll["gender"] == "W";
                    ents.AddToPersonalData(data);
                    SocialMessages msg = SocialMessages.CreateSocialMessages(Constants.ADRESAT_ROBOT,
                                                                             Constants.ADRESAT_GAMEMASTER, DateTime.Now, Constants.SOCIALMESSAGE_TYPE_EVENT,
                                                                             Guid.NewGuid(),
                                                                             "Регистрация нового пользователя - " +
                                                                             coll["username"], string.Format("Пользователь {0} прошел регистрацию. Реферрер - {1}", coll["username"], Utils.GetUserByID(user.Referrer.ToString()).Username));
                    ents.SocialMessages.AddObject(msg);

                    foreach (var sm in ents.SocialMessages.Where(r => r.MsgTo == Constants.ADRESAT_EVERYBODY).ToList())
                    {
                        SocialMessagesStatus stat = SocialMessagesStatus.CreateSocialMessagesStatus(userID, sm.MsgID,
                                                                                                    Constants.
                                                                                                        SOCIALMESSAGE_STATUS_DELETED,
                                                                                                    1);
                        ents.AddToSocialMessagesStatus(stat);
                    }
                    ents.SaveChanges();
                    ents.Dispose();
                    Utils.UseCode(coll["code"], userID);
                    Utils.SendTemplate(Constants.TEMPLATE_CONFIRMREGISTRATION, coll["email"], true, Utils.GetServerAddress(), coll["username"], Utils.GetServerURL(Request)+"/Auth/Validate/"+user.ValidationKey);
                    LogService.Info(Utils.GetPrincipalName(), Constants.COMPONENT_REGISTRATION, string.Format("User {0} registered", user.Username));
                    return new RedirectResult("/Auth/UserCreated");
                }
            }
        }

        [Authorized]
        public ActionResult ReSendValidation()
        {
            if (Utils.IsUserValidated())
            {
                return new RedirectResult("/");
            }
            LogService.Info(Utils.GetPrincipalName(), Constants.COMPONENT_REGISTRATION, "Validate User: User re-requested validation");
            Users u = Utils.GetCurrentUser();
            Utils.SendTemplate(Constants.TEMPLATE_CONFIRMREGISTRATION, u.Email, true, Utils.GetServerAddress(), u.Username, Utils.GetServerURL(Request) + "/Auth/Validate/" + u.ValidationKey);
            return View();
        }

        public ActionResult Validate(string id)
        {
            string code = id;
            string name = Utils.ValidateUser(code);
            if (name == null)
            {
                LogService.Error(Utils.GetPrincipalName(), Constants.COMPONENT_REGISTRATION, string.Format("Validate User: User not found for code", code));
                return new RedirectResult("/");
            }
            HeritageEntities ents = new HeritageEntities();
            SocialMessages msg = SocialMessages.CreateSocialMessages(Constants.ADRESAT_ROBOT,
                                                         Constants.ADRESAT_GAMEMASTER, DateTime.Now, Constants.SOCIALMESSAGE_TYPE_EVENT,
                                                         Guid.NewGuid(),
                                                         "Валидация пользователя " + name, string.Format("Пользователь {0} прошел валидацию.", name));
            ents.SocialMessages.AddObject(msg);
            ents.SaveChanges();

            LogService.Info(Utils.GetPrincipalName(), Constants.COMPONENT_REGISTRATION, string.Format("Validate User: User {0} validated", name));
            ViewData["User"] = name;
            return View();
        }

        public ActionResult WrongCode()
        {
            return View();
        }
        public ActionResult WrongCreds()
        {
            return View();
        }
        public ActionResult UserCreated()
        {
            return View();
        }

        public ActionResult NeedValidation()
        {
            return View();
        }

        public ActionResult About()
        {
            return View();
        }
        public ActionResult SignOut()
        {
            LogService.Info(Utils.GetPrincipalName(), Constants.COMPONENT_SIGNIN, "User signed out");
            Utils.SignOut();
            return new RedirectResult("/");
        }
    }
}
